<!DOCTYPE group PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<group>

<h1> Documentation </h1>

<ul>
  <li><a href="%pathto:doc.structure;">Framework structure</a>
  <ul>
    <li><a href="%pathto:doc.extractors;">Image feature extractors</a></li>
    <li><a href="%pathto:doc.datasets;">Datasets</a></li>
    <li><a href="%pathto:doc.datasets;">Benchmarks</a></li>
  </ul>
  </li>
  <li><a href="%pathto:doc.parallel;">Parallelisation</a></li>
  <li><a href="%pathto:doc.helpers;">Helpers</a>
  <ul>
    <li><a href="%pathto:doc.caching;">DataCache</a></li>
    <li><a href="%pathto:doc.logging;">Logger</a></li>
  </ul>
  </li>
  <li><a href="%pathto:doc.refs;">References</a></li>
</ul>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h2 id="doc.structure">Framework structure</h2>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->

<p>
<b>VLBenchmarks</b> is organised into four parts, corresponding to
an equal number of MATLAB packages (namespaces):</p>
<ul>

<li><a href="%pathto:doc.extractors;">Image feature extractors</a>
(<strong><code>localFeatures</code></strong>). This package contains
wrappers for features detectors and descriptors. Add your own wrapper
here to evaluate your features.</li>

<li><a href="%pathto:doc.datasets;">Datasets</a>
(<strong><code>datasets</code></strong>) This package contains code
that manages (downloads and reads) benchmark data. The most common use
is to adopt one of the supported standard benchmarks, but you may want
to add a wrapper to your own dataset here.</li>

<li><a href="%pathto:doc.benchmarks;">Feature benchmarks.</a>
(<strong><code>benchmarks</code></strong>). This package contains the
benchmarking code.</li>

<li><a href="%pathto:doc.helpers;">Supporting functions and classes</a>
(<strong><code>helpers</code></strong>). </li>
</ul>

<p>Options of functions and of class objects are passed as optional 
  function/constructor arguments in the following format:</p>
<precode type="matlab">
  function(obligatoryParams,'OptionName',OptionValue,...)
</precode>
<p>Available options are listed in help string of functions or classes. 
It is not possible to change options of already constructed object.</p>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h3 id="doc.extractors">Feature objects</h3>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->

<p>All classes from package <code>localFeatures</code> are subclasses 
of <code>GenericLocalFeaturesExtractor</code>. In VLBenchmarks those
feature extractors wrappers are already implemented:
</p>

<table border="1" width="600px">
    <tr>
        <th rowspan="2">Class name</th>
        <th colspan="2" class="center">Extracts</th>
        <th colspan="3" class="center">Supported platforms</th>
        <th rowspan="2" class="center">Note</th>
    </tr>
    <tr>
        <th class="center">Feat.</th>
        <th class="center">Descr.</th>
        <th class="center">WIN</th>
        <th class="center">LNX</th>
        <th class="center">OS X</th>
    </tr>
    <tr>
        <td>VlFeatSift</td>
        <td class="center">Y</td>
        <td class="center">Y</td>
        <td class="center">Y</td>
        <td class="center">Y</td>
        <td class="center">Y</td>
        <td>Built-in <a href="#doc.ref1">[1]</a>, DoG detector, SIFT descriptor</td>
    </tr>
    <tr>
        <td>VlFeatCovdet</td>
        <td class="center">Y</td>
        <td class="center">Y</td>
        <td class="center">Y</td>
        <td class="center">Y</td>
        <td class="center">Y</td>
        <td>Built-in, DoG, Hessian and Harris detectors and their variants.</td>
    </tr>
    <tr>
        <td>VlFeatMser</td>
        <td class="center">Y</td>
        <td class="center">N</td>
        <td class="center">Y</td>
        <td class="center">Y</td>
        <td class="center">Y</td>
        <td>Built-in <a href="#doc.ref1">[1]</a></td>
    </tr>
    <tr>
        <td>VggAffine</td>
        <td class="center">Y</td>
        <td class="center">N</td>
        <td class="center">N</td>
        <td class="center">Y</td>
        <td class="center">N</td>
        <td>Affine feature frame detection<a href="#doc.ref2">[2]</a></td>
    </tr>
    <tr>
        <td>VggDescriptor</td>
        <td class="center">N</td>
        <td class="center">Y</td>
        <td class="center">N</td>
        <td class="center">Y</td>
        <td class="center">N</td>
        <td>Descriptor calculation from <a href="#doc.ref2">[2]</a></td>
    </tr>
    <tr>
        <td>Ebr</td>
        <td class="center">Y</td>
        <td class="center">N</td>
        <td class="center">N</td>
        <td class="center">Y</td>
        <td class="center">N</td>
        <td>Edge based region detector <a href="#doc.ref2">[2]</a></td>
    </tr>
    <tr>
        <td>Ibr</td>
        <td class="center">Y</td>
        <td class="center">N</td>
        <td class="center">N</td>
        <td class="center">Y</td>
        <td class="center">N</td>
        <td>Intensity based region detector <a href="#doc.ref2">[2]</a></td>
    </tr>
    <tr>
        <td>CmpBinHessian</td>
        <td class="center">Y</td>
        <td class="center">N</td>
        <td class="center">N</td>
        <td class="center">Y</td>
        <td class="center">N</td>
        <td>Hessian affine <a href="#doc.ref3">[3]</a></td>
    </tr>
</table>


<h4 id="doc.benchmarkowndet">Benchmarking your own feature extractor</h4>

<p> The VLBenchmarks framework is easily extensible with your own image feature extraction
algorithm. Your feature extractor wrapper has to be a subclass
of <code>GenericLocalFeaturesExtractor</code> class and has to implement
method <code>extractFeatures(imgPath)</code> and/or
<code>extractDescriptors(imgPath, frames)</code> depending on your
algorithm abilities. </p>

<p>You can use existing infrastructure of the benchmark.
For example, by inheriting from <code>GenericLocalFeatureExtractor</code>
you also inherit <code>helpers.Logger</code> class which implements
simple logger. See <a href="%pathto:doc.logging;">Logging</a> for details.</p>

<p>Another helper class used with the most of the built in detectors is 
<code>helpers.GenericInstaller</code>. This class handles installation process
and supports to define class dependencies on web-located archives, mex files
and other classes.</p>

<p>This example shows a feature extractor which
supports both feature frame detection and descriptor calculation. This
class supports downloading and compiling mex source code of the
detector.</p>

<precode type="matlab">
classdef ExtractorY &lt; localFeatures.GenericLocalFeatureExtractor &amp; ...
  helpers.GenericInstaller
% localFeatures.DetectorY Y feature frames detector.

%   localFeatures.DetectorY('OptionName', optionValue) Construct new wrapper
%   of Y image features extractor. This algorithm is able to both detect image
%   features and compute their descriptors.
%
%   This class support caching and automatic installation. The sources are
%   downloaded from:
%
%   http://supercoolstuff.com/dreamdetector.zip
%
% Options:
%   DetOption:: 0
%     Serious configuration stuff...
%
%   AutoInstall:: true
%     Install dependencies during object construction.
%
%   This class accepts helpers.Logger options.
%
% See also: localFeatures.DetectorX helpers.Logger
  properties (SetAccess=private, GetAccess=public)
    Opts = struct('detOption',0); % Default option value
  end
  properties (Constant)
    % Location of your code
    Dir = fullfile('data','software','exy');
    % URL with the source codes
    Url = 'http://supercoolstuff.com/dreamdetector.zip';
    % MEX files needed to be compiled for the detector
    SrcFiles = {fullfile(localFeatures.ExtractorY.Dir,'y_algorithm.c')};
    % MEX files needed to be compiled for the detector
    MexFiles = ...
      {fullfile(localFeatures.ExtractorY.Dir,['y_algorithm.',mexext])};
  end
  methods
    function obj = ExampleLocalFeatureExtractor(varargin)
      obj.Name = 'Detector Y'; % Name of the wrapper
      varargin = obj.configureLogger(obj.Name,varargin); % Configure logger
      varargin = obj.checkInstall(varargin); % Check whether installed
      obj.Opts = vl_argparse(obj.Opts,varargin); % Parse object options
      obj.setup(); % Setup the paths
    end

    function setup(obj)
      % setup Setup extractorY paths.
      addpath(obj.Dir);
    end
    
    function [frames descriptors] = extractFeatures(obj, imagePath)
      % extractFeatures Extract features from an image
      %   FRAMES = extractFeatures(IMG_PATH) Detect features in image IMG_PATH
      %   using the Y algorithm.
      %
      %   [FRAMES DESCRIPTORS] = extractFeatures(IMG_PATH) Detect frames and
      %   compute their descriptors using the Y algorithm.
      frames = obj.loadFeatures(imagePath,nargout > 1); % Check cache
      if numel(frames) > 0; return; end;
      descriptors = [];
      obj.info('Computing frames of image %s.',getFileName(imagePath));
      if nargout == 1
        frames = y_algorithm(imagePath, obj.Opts{:});
        obj.debug('Frames computed in %gs',toc(startTime));
      elseif nargout == 2
        [frames descriptors] = y_algorithm(imagePath, obj.Opts{:});
        obj.debug('Frames and descriptors computed in %gs',toc(startTime));
      end
      obj.storeFeatures(imagePath, frames, descriptors); % Cache the results
    end

    function [frames descriptors] = extractDescriptors(obj, imagePath, frames)
      % extractDescriptors Extract descriptors of given frames
      startTime = tic;
      obj.info('Computing descriptors of image %s.',getFileName(imagePath));
      [frames, descriptors] = y_algorithm(imagePath,frames,obj.Opts{:});
      obj.debug('Descriptors computed in %gs',toc(startTime));
    end

    function signature = getSignature(obj)
      signature = [helpers.struct2str(obj.Opts),';',...
        helpers.fileSignature(obj.MexFiles)]; % Detector unique signature
    end
  end
  methods (Access=protected)
    % Define which archives should be downloaded and where extracted
    function [urls dstPaths] = getTarballsList(obj)
      import localFeatures.*;
      urls = {DetectorY.Url};
      dstPaths = {DetectorY.Dir};
    end
    % Define which mex files should be compiled
    function [srclist flags] = getMexSources(obj)
      import helpers.*;
      srclist = obj.SrcFiles;
      % Flags passed to mex command
      flags = {};
    end
  end
end
</precode>


<p> Method <code>extractFeatures(imgPath)</code> can be called with one output
argument when only feature frames need to be detected. When called with two
output arguments, it extracts both feature frames and descriptors. This may
seem to be dual to the <code>extractDescriptors()</code> method however some
detectors does not support computation of descriptors of given frames. </p>

<p> To cache your detected features, you can use <code>loadFeatures()</code>
or <code>obj.storeFeatures()</code> methods. However these methods need to
implement method <code>obj.getSignature()</code> which generates unique string
signature of the detector parameters. It is also useful to include signature
of the detector binary file (<code>helpers.fileSignature</code>). Caching can
be enabled/disables with methods <code>obj.enableCaching()</code>,
<code>obj.disableCaching()</code> </p>
 
<p> To see details about logging, class options and installation framework,
see the <code>localFeatures.ExampleLocalFeatureExtractor</code> class. </p>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h3 id="doc.datasets">Datasets</h3>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->

<p>All datasets are subclasses of abstract <code>GenericDataset</code> which
defines method <code type="matlab">getImagePath(imageNumber)</code> to access
dataset images. Number of images in the dataset can be obtained from
object property <code type="matlab">obj.NumImages</code>.</p>

<p>Repeatability benchmark needs datasets which inherits from class
<code>GenericTransfDataset</code>. This benchmark needs method <code
type="matlab">getTransformation(imageNumber)</code> which returns homography
between a dataset image and a reference image (first image).</p>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h4 id="doc.datasets">VggAffineDataset</h4>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->

<p>Wrapper of the datasets from <a href="#doc.ref2">[2]</a> is implemented in
class <code>VggAffineDataset</code> and is a subclass of
<code>GenericTransfDataset</code>. Datasets data are available and downloaded
from  <a href="http://www.robots.ox.ac.uk/~vgg/research/affine/">VGG
website</a>.</p>

<p>Available categories (accessible through option <code>'Category'</code>) are:</p>

<table border="1" width="400px">
    <tr>
        <th class="center">Category Name</th>
        <th class="center">'Category' option value</th>
        <th class="center">Image transformation</th>
    </tr>
    <tr>
        <td class="center">Wall</td>
        <td class="center"><code>'wall'</code></td>
        <td class="center">Viewpoint angle</td>
    </tr>
    <tr>
        <td class="center">Boat</td>
        <td class="center"><code>'boat'</code></td>
        <td class="center">Scale changes</td>
    </tr>
    <tr>
        <td class="center">Bark</td>
        <td class="center"><code>'bark'</code></td>
        <td class="center">Scale changes</td>
    </tr>
    <tr>
        <td class="center">Bikes</td>
        <td class="center"><code>'bikes'</code></td>
        <td class="center">Increasing blur</td>
    </tr>
    <tr>
        <td class="center">Trees</td>
        <td class="center"><code>'trees'</code></td>
        <td class="center">Increasing blur</td>
    </tr>
    <tr>
        <td class="center">Leuven</td>
        <td class="center"><code>'leuven'</code></td>
        <td class="center">Decreasing light</td>
    </tr>
    <tr>
        <td class="center">UBC</td>
        <td class="center"><code>'ubc'</code></td>
        <td class="center">JPEG compression</td>
    </tr>
</table>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h4 id="doc.datasets">VggRetrievalDataset</h4>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->

<p>For the retrieval benchmark <code>VggRetrievalDataset</code> wraps around 
datasets introduced in <a href="#doc.ref4">[4]</a>, <a href="#doc.ref5">[5]</a>
These datasets provide both a set of images and a set of queries. Each query
is specified by the query image, a bounding box and
three subset of images:</p>

<ul>
  <li><strong>Good</strong> A nice, clear picture of the object/building</li>
  <li><strong>Ok</strong> More than 25% of the object is clearly visible.</li>
  <li><strong>Junk</strong> Less than 25% of the object is visible, or there are very high 
    levels of occlusion or distortion.</li>
  <li><strong>Bad</strong> Object not present.</li>
</ul>

<p>A query is accessible through method <code>getQuery(queryNum)</code> which 
returns a structure with the following format:</p>

<precode type='matlab'>
>> dst = datasets.VggRetrievalDataset();
(INFO)  VggRetrievalDataset:  Loading dataset VggRetrievalDataset.
(DEBUG) VggRetrievalDataset:  Size of the images subset: 945
>> query = dst.getQuery(1)

query = 

         name: 'all_souls_1'        % Query name
    imageName: 'all_souls_000013'   % Name of the query image
      imageId: 8                    % Query image id
          box: [4x1 double]         % Query bounding box [xmin ymin xmax ymax]
         good: [1x24 double]
           ok: [1x54 double]
         junk: [1x33 double]
</precode>

<p>The image subsets are numeric arrays with image IDs. To obtain a path of
  a certain image from these subsets, you can simply call: </p>

<precode type="matlab">
>> dst.getImagePath(query.junk(1))

ans =

data/datasets/vggRetrievalDataset/oxbuild/all_souls_000220.jpg
</precode>

<p>Number of all images in the dataset is stored in property
<code type="matlab">obj.NumQueries</code>.</p>

<p>Currently, two dataset categories are available:</p>

<table border="1" width="500px">
    <tr>
        <th class="center">Category Name</th>
        <th class="center">'Category' option value</th>
        <th class="center">Number of images</th>
        <th class="center">Number of queries</th>
        <th class="center">Source</th>
    </tr>
    <tr>
        <td>The Oxford Buildings Dataset <a href="#doc.ref4">[4]</a></td>
        <td class="center"><code>'oxbuild'</code></td>
        <td class="center">5062</td>
        <td class="center">55</td>
        <td><a href="http://www.robots.ox.ac.uk/~vgg/data/oxbuildings/">link</a></td>
    </tr>
    <tr>
        <td>The Paris Dataset<a href="#doc.ref5">[5]</a></td>
        <td class="center"><code>'paris'</code></td>
        <td class="center">6412</td>
        <td class="center">55</td>
        <td><a href="http://www.robots.ox.ac.uk/~vgg/data/parisbuildings/">link</a></td>
    </tr>
</table>

<p>These datasets usually contain thousands of images. It is
possible to work only with its subset specified by these constructor
parameters:</p>

<precode>
    GoodImagesNum
      Number of 'Good' images preserved in the database. When inf, all
      images preserved.
 
    OkImagesNum
      Number of 'ok' images preserved in the database. When inf, all
      images preserved.
 
    JunkImagesNum
      Number of 'junk' images preserved in the database. When inf, all
      images preserved.
 
    BadImagesNum
      Number of 'junk' images preserved in the database. When inf, all
      images preserved.
 
    SamplingSeed
      Seed of the random number generator used for sampling the image
      dataset.
</precode>

<p>Subsets are sampled used uniform random sampling. You can change the
particular sampling by changing the seed of random number generator with 
parameter <code>SamplingSeed</code>.
</p>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h3 id="doc.benchmarks">Benchmarks</h3>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->

<p>All benchmark classes are subclasses of abstract class 
<code>GenericBenchmark</code>. 
Currently three benchmarks are implemented.</p>

<p><code>RepeatabilityBenchmark</code> is based on tests introduced in 
<a href="#doc.ref2">[2]</a>. For details about this test see the 
help string of the <code>RetrievalBenchmark</code> class or see 
<a href="%pathto:tut.repeatability;">repeatability tutorial</a>.
Because this test is mostly reimplementing the original test, wrapper of the
original benchmark <code>IjcvOriginalBenchmark</code> is also available. This
class directly calls the <code>repeatability.m</code> script.
</p>

<p><code>RetrievalBenchmark</code> class implements simple retrieval benchmark
of image features detectors. For details see help string of the class or see
<a href="%pathto:tut.retrieval;">image retrieval benchmark tutorial</a>. </p>

<p>Currently the image retrieval benchmark depends on the <a
href="https://gforge.inria.fr/projects/yael">Yael</a> library which is not
available for Microsoft Windows platforms.</p>


<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h2 id="doc.parallel">Parallelisation</h2>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->

<p>The way how to parallelise is different for the repeatability and retrieval 
benchmark but both approaches use Matlab Parallel Computing Toolbox. 
For details about this toolbox, see its 
<a href="http://www.mathworks.com/help/distcomp/index.html">documentation</a>.
</p>

<p> Parallelisation of the repeatability benchmark can be done
by interchanging <code>for</code> with <code>parfor</code> in any level, 
e.g.:</p>

<precode type="matlab">
% Prevent cache to clear the last recently used items
helpers.DataCache.disableAutoclear();
for di = 1:numDetectors
  % Extract features from the first image to avoid race condition
  % as several processes may try to write the same file.
  % Features does not have to be stored in any variable as they are
  % cached.
  detectors{di}.extractFeatures(dataset.getImagePath(1));
  parfor imageIdx = 2:numImages
    % Run the repeatability benchmark
  end
end
helpers.DataCache.enableAutoclear();
</precode>

<p>This is possible thanks to the fact that the cache system depends only on the 
file system context and does not share any variables. However it does not
implement any synchronisation mechanisms.
If the loops are properly designed, each process works with different data.
However cache autoclear has to be disabled as it can produce situations when 
two processes are trying to delete the same files.
</p>

<p>The image retrieval benchmark is already parallelised and the class
<code>RetrievalBenchmark</code> uses several parfor loops for both features
extraction and KNN search.</p>

<p>In the case of KNN search you can advantage both from symmetric processing 
and distributed computing as the Yael KNN uses OpenMP to run its algorithms
in multiple threads.</p>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h2 id="doc.helpers">Helpers</h2>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->

<p> Package helpers contains several classes and functions which are used in
the rest of the project. <code>Logger</code> and <code>DataCache</code>
classes are used almost in all classes therefore are described more in the
following text. </p>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h3 id="doc.caching">Caching</h3>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->

<p>This project extensively caches its results using key-value caching system.
The key string is usually created based on the properties of input data and
processing algorithm. Data itself can be any Matlab data object and are stored
as <code>*.mat</code> files in directory <code>./data/cache</code>. The
target filename is created as MD5 sum of the key.</p>

<p>Binary data are usually distinguished by a signature of the source file.
File signature contains the file name and last modification date of the file.
This is also used for algorithm binaries. Among that, the signature usually
contain algorithm parameters as their values affect the results.</p>

<h4 id="doc.caching.methods">DataCache methods</h4>

<p>Caching is implemented in class <code>helpers.DataCache</code> and has only
static methods, in order to be able to use it in parallel where no memory is
shared among processes. This class implements the following methods:</p>

<ul>
<li><code>data = DataCache.getData(key)</code> Get data identified by a 
  string key. If the data has not been found, return [].</li>
                        
<li><code>storeData(data,key)</code> Store data identified by key.</li>
<li><code>res = hasData(key)</code> Check whether data are cached.</li>


<li><code>removeData(key)</code> Remove particular data from the cache.</li>

<li><code>clearCache()</code> Delete the last recently used data to limit 
  the overall size of the cached data to <code>DataCache.maxDataSize</code> limit.
</li>

<li><code>deleteAllCachedData()</code> Delete all cached data.</li>

<li><code>disableAutoClear()</code> Temporarily disable the autoclear 
  function. Cannot be called in parallel function as it creates a lock file.
</li>

<li><code>enableAutoClear()</code>Enable autoClear after disableAutoClear. 
  Cannot be called in parallel part of code as it deletes a lock file.</li>
</ul>

<h4 id="doc.caching.properties">DataCache properties</h4>

<p>The caching properties can be changed only in the
<code>helpers/DataCache.m</code>  source code by changing the class constant
properties:</p>

<ul>
<li><code>maxDataSize</code> Maximal storage space occupied by 
  cached data in Bytes.</li>
<li><code>dataPath</code> Directory where to store cached data</li>
<li><code>dataFileVersion</code> Version of the .mat file used for data 
  storage. See 'help save' for details.</li>
<li><code>autoClear</code> Check whether storage size has not exceeded 
  the allowed size after each storeData method call. If so, the last recently
  used data are removed</li>
<li><code>disable</code> Globally disable caching.</li>
</ul>

<p>Please note that the standard Matlab behaviour is to set these values only
once when the class file is loaded for the first time. Therefore to apply the
options you must call:</p>

<precode type="matlab">
>> clear all;
</precode>


<h4 id="doc.caching.autoclear">Auto clear functionality</h4>

<p>Caching system implements a way how to limit the overall size of the
cached data, further denoted as an <i>autoclear</i> function. It
checks the size of the files in the cache directory and removes the last recently used
items (based on the file modification date) to limit the storage usage.
To globally disable autoclear set the class property
<code>helpers.DataCache.autoClear</code> to false. You can also disable it 
temporarily by calling method <code>helpers.DataCache.disableAutoclear()</code> 
which creates a lock file.
It is recommended to call this method before running parallel code to prevent
two processes to delete the same files.</p>

<h4 id="doc.caching.disabling">Disable caching</h4>

<p>Cache can be disabled globally by setting the constant property
<code>helpers.DataCache.autoClear</code> to true. Also several framework
classes implements methods <code>disableCaching()</code> and 
<code>enableCaching()</code> to control the caching behaviour of a single
class.</p>

<p>Cache does not support data invalidation. However to invalidate cached 
data of a certain detector you can use a simple trick to change the detector 
binary modification date:</p>

<precode type="matlab">
>> helpers.touch('./data/software/det_binary');
</precode>

<h4 id="doc.caching.limits">DataCache limits</h4> 

<p>As the cache depends heavily on a file system it is basically limited by a
number of files in a single directory which depends on your operating system.
Big directory structures can lead to slow file operations and therefore the
cache operations can take longer. Thus it is recommended to clear the cache
once a while (specially when using network file system).</p>



<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h3 id="doc.logging">Logger</h3>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<p>Several classes in the framework uses logging implemented
in class <code>helper.Logger</code> class. This class supports both sending
the events to std output or writing them to a log file. 
Following events, inspired by the apache Log4j framework, are supported:</p>

<table border="1" width="500px">
    <tr>
        <th class="center">Event name</th>
        <th class="center">'VerboseLevel' value</th>
        <th class="center">Usage</th>
    </tr>
    <tr>
        <td class="center">TRACE</td>
        <td class="center"><code>3</code></td>
        <td> finer-grained informational events than the DEBUG.</td>
    </tr>
    <tr>
        <td class="center">DEBUG</td>
        <td class="center"><code>2</code></td>
        <td>Information useful for debugging.</td>
    </tr>
    <tr>
        <td class="center">INFO</td>
        <td class="center"><code>1</code></td>
        <td>Informational messages about the application progress.</td>
    </tr>
    <tr>
        <td class="center">WARN</td>
        <td class="center"><code>0</code></td>
        <td>Logs potentially harmful situations. Calls 
          <code>warn</code> command to show the backtrace.</td>
    </tr>
    <tr>
        <td>ERROR</td>
        <td class="center"><code>-1</code></td>
        <td>Several errors which does not allow application
          to continue. Calls Matlab <code>error</code> function.</td>
    </tr>
</table>

<p>The verbose level can be set both globally editing
the constant properties of class <code>helpers.Logger</code> 
or locally for each object which inherits the <code>Logger</code> 
class by providing the <code>'OptionName',OptionValue</code> parameters
to the class constructor call. Supported options are:</p>

<precode>
   VerboseLevel:: [helpers.Logger.DEBUG]
    Maximal verbosity level of messages sent to stdout. If set to OFF all
    messages are ignored, even errors would not stop the program execution.

  FileVerboseLevel:: [helpers.Logger.OFF]
    Maximal verbosity level of messages which are written to a log file.

  LogFile :: [./data/log]
     Path to a log file.
</precode>

<p>If you want to change the format of the log output, just adjust the methods
<code type="matlab">helpers.Logger.displayLog</code> and 
<code type="matlab">helpers.Logger.logToFile</code> according to your 
aesthetic preferences.</p>

<h4 id="doc.logging.using">Using Logger in your own classes</h4>

<p>You can also use logger on your class as well simply by specifying the 
<code>helpers.Logger</code> as a superclass. Here is a simple template how
to do it and how to properly configure the logger:</p>

<precode type="matlab">
  classdef MyClass &lt; helpers.Logger
    methods
      function obj = RepeatabilityBenchmark(varargin)
        varargin = obj.configureLogger('MyClassName',varargin);
        % Now you can process varargin for your arguments
        obj.info('Constructed.');
      end
    end
  end
</precode>

<p>And constructing your object you will get:</p>

<precode type="matlab">
>> MyClass();
(INFO)  MyClassName:  Constructed.
</precode>

<h4 id="doc.logging.using">Logging to a file and distributed computing</h4>

<p>When your computation are being computed with several processes, possibly 
on several computers, having a single logging file may lead to inconsistent
data. That is why we would like to create separate files for each Matlab
process. This is generally a difficult task as the <code>parfor</code>
environment does not include any information about the process.</p>

<p>But simple trick can be used. Matlab creates default values for
object properties only once when the file is loaded for the first time.
And in classic matlabpool each lab has got its own MATLAB process,
therefore a log file name in the <code>helpers.Logger</code> can be set for 
example to:</p>

<precode type="matlab">
LogFile = fullfile('data',['log-',helpers.hostname(),...
  randsample(char(97:122),5)]);
</precode>

<p>To test we can call the following code:</p>

<precode type="matlab">
>> matlabpool 5;
>> import helpers.Logger;
>> parfor i=1:3
  for j=1:3
    obj = Logger();
    fprintf('Proc. #%d Obj. #%d: %s\n',i,j,obj.LogFile);
  end;
end;

Proc. #1 Obj. #1: data/log-comp02xcdqv
Proc. #1 Obj. #2: data/log-comp02xcdqv
Proc. #1 Obj. #3: data/log-comp02xcdqv
Proc. #2 Obj. #1: data/log-comp02lwmxr
Proc. #3 Obj. #1: data/log-comp02scirh
Proc. #3 Obj. #2: data/log-comp02scirh
Proc. #2 Obj. #2: data/log-comp02lwmxr
Proc. #2 Obj. #3: data/log-comp02lwmxr
Proc. #3 Obj. #3: data/log-comp02scirh
</precode>

<p>You can see that each process generated the random string only once.
If the parfor would be distributed on more computers, the 
<code>hostname()</code> value would change as well.</p>

<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<h2 id="doc.refs">References</h2>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->

 <ol>
  <li id="doc.ref1">A. Vedaldi and B. Fulkerson. 
  <strong>VLFeat:</strong> An Open and Portable Library
  of Computer Vision Algorithms, 
  <a href="http://www.vlfeat.org/">vlfeat.org</a>, 2008.
  </li>
  <li id="doc.ref2"> K. Mikolajczyk, T. Tuytelaars,
  C. Schmid, A. Zisserman, J. Matas, F. Schaffalitzky, T. Kadir, and
  L. Van Gool. A comparison of affine region detectors. IJCV,
  1(65):43–72, 2005.</li>
  <li id="doc.ref3">Perdoch, M. and Chum, O. and Matas, J. 
  Efficient Representation of Local Geometry for Large Scale Object 
  Retrieval. In proceedings of CVPR09, 2009.
  </li>
  <li id="doc.ref4">J. Philbin, O. Chum, M. Isard, J. Sivic and 
  A. Zisserman. Object retrieval with large vocabularies and fast spatial 
  matching CVPR, 2007</li> 
  <li id="doc.ref5">J. Philbin, O. Chum, M. Isard, J. Sivic and 
  A. Zisserman., Lost in Quantization: Improving Particular Object Retrieval 
  in Large Scale Image Databases (2008)</li>
 </ol>
</group>
